package ch.bfh.android.WhereAmI;

import java.util.Vector;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.location.Location;
import android.os.Binder;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.util.Log;
import android.widget.Toast;
import ch.simplix.android.geo.discoverer.gps.GPSDiscovererService;
import ch.simplix.android.net.discoverer.bluetooth.BluetoothDiscovererService;
import ch.simplix.android.net.discoverer.bluetooth.BluetoothMeasurement;
import ch.simplix.android.net.discoverer.bluetooth.BluetoothReading;
import ch.simplix.android.net.discoverer.gsm.GSMDiscovererService;
import ch.simplix.android.net.discoverer.gsm.GSMMeasurement;
import ch.simplix.android.net.discoverer.gsm.GSMReading;
import ch.simplix.android.net.discoverer.wifi.WiFiMeasurement;
import ch.simplix.android.net.discoverer.wifi.WiFiReading;
import ch.simplix.android.net.discoverer.wifi.WifiDiscovererService;

public class LocationService extends Service {
	public static final String EXTRA_DISCOVER = "discover";
	public static final String EXTRA_SENDER = "senderAdress";
	private final LocalBinder binder = new LocalBinder();
	private BluetoothDiscovererService bluetoothDiscovererService;
	private GSMDiscovererService gsmDiscovererService;
	private WifiDiscovererService wifiDiscovererService;
	private BluetoothMeasurement btMeasurement;
	private GPSDiscovererService gpsDiscovererService;
	private Location gpsMeasurement;
	private GSMMeasurement gsmMeasurement;
	private WiFiMeasurement wifiMeasurement;
	private String senderAdress;

	@Override
	public void onCreate() {
		registerReceiver(bluetoothReceiver, new IntentFilter(
				BluetoothDiscovererService.BLUETOOTH_ACTION));

		registerReceiver(gsmReceiver, new IntentFilter(
				GSMDiscovererService.GSM_ACTION));

		registerReceiver(wifiReceiver, new IntentFilter(
				WifiDiscovererService.WIFI_ACTION));

		registerReceiver(gpsReceiver, new IntentFilter(GPSDiscovererService.GPS_ACTION));
		super.onCreate();
	}

	@Override
	public void onDestroy() {
		unregisterReceiver(bluetoothReceiver);
		unregisterReceiver(gsmReceiver);
		unregisterReceiver(wifiReceiver);
		unregisterReceiver(gpsReceiver);
		
		unbindService(bluetoothDiscovererServiceConnection);
		unbindService(gsmDiscovererServiceConnection);
		unbindService(wifiDiscovererServiceConnection);
		unbindService(gpsDiscovererServiceConnection);
		super.onDestroy();
	}

	@Override
	public void onStart(Intent intent, int startId) {
		super.onStart(intent, startId);
		if(isInAirplaneMode(this))
		{
			toggleAirplaneMode(this);
		}
		boolean startDiscover = intent.getExtras().getBoolean(EXTRA_DISCOVER);
		senderAdress = intent.getExtras().getString(EXTRA_SENDER);
		if (startDiscover) {
			bindService(new Intent(this, BluetoothDiscovererService.class),
					bluetoothDiscovererServiceConnection,
					Context.BIND_AUTO_CREATE);

			bindService(new Intent(this, GSMDiscovererService.class),
					gsmDiscovererServiceConnection, Context.BIND_AUTO_CREATE);

			bindService(new Intent(this, WifiDiscovererService.class),
					wifiDiscovererServiceConnection, Context.BIND_AUTO_CREATE);
			
			bindService(new Intent(this, GPSDiscovererService.class),
					gpsDiscovererServiceConnection, Context.BIND_AUTO_CREATE);

			Log.d("WhereAmI.LocationService", "onStart");
		}
	}

	private void checkForMeasurements() {
		SharedPreferences prefs = PreferenceManager
				.getDefaultSharedPreferences(getBaseContext());
		String prefGSMKey = getString(R.string.prefGSMKey);
		boolean readGSM = prefs.getBoolean(prefGSMKey, true);

		if ((btMeasurement == null && readGSM) || (gsmMeasurement == null)
				|| (wifiMeasurement == null)) {
			return;
		}
		StringBuilder sb = new StringBuilder();
		// sb.append("g;");
		Vector<GSMReading> gsmReadings = gsmMeasurement.getGSMReadings();
		for (int i = 0; i < gsmReadings.size(); i++) {
			GSMReading r = gsmReadings.get(i);
			sb.append(r.getAreaId());
			sb.append(".");
			sb.append(r.getCellId());
			if (i >= 2) {
				sb.append(";");
				break;
			} else {
				sb.append(",");
			}
		}
		Vector<BluetoothReading> btReadings = btMeasurement
				.getBluetoothReadings();
		for (int i = 0; i < btReadings.size(); i++) {
			BluetoothReading r = btReadings.get(i);
			sb.append(r.getFriendlyName());
			sb.append(".");
			sb.append(r.getBluetoothAddress());
			if (i >= 2) {
				sb.append(";");
				break;
			} else {
				sb.append(",");
			}
		}
		Vector<WiFiReading> wifiReadings = wifiMeasurement.getWiFiReadings();
		for (int i = 0; i < wifiReadings.size(); i++) {
			WiFiReading r = wifiReadings.get(i);
			sb.append(r.getSsid());
			sb.append(".");
			sb.append(r.getBssid());
			if (i >= 2) {
				sb.append(";");
				break;
			} else {
				sb.append(",");
			}
		}
		if(gpsMeasurement!=null){
			sb.append(gpsMeasurement);
		}
		// todo: split to multiple sms!
		if (sb.length() <= 160) {
			sendSMS(senderAdress, sb.toString());
		}
		Toast.makeText(getApplicationContext(),
				"lenght=" + sb.length() + "#" + sb.toString(),
				Toast.LENGTH_LONG).show();
		Log.d("WhereAmI.LocationService", "Text: "+sb.toString());

	}

	private void sendSMS(String phoneNumber, String message) {
		// PendingIntent pi = PendingIntent.get getActivity(this, 0, new
		// Intent(this, LocationService.class), 0);
		// SmsManager sms = SmsManager.getDefault();
		// // sms.sendTextMessage(phoneNumber, null, message, sentIntent, null);
		// sms.sendTextMessage(phoneNumber, null, message, null, null);
	}

	private static boolean isInAirplaneMode(Context context){
		ContentResolver cr = context.getContentResolver();
		return Settings.System.getInt(cr,
				Settings.System.AIRPLANE_MODE_ON, 0) != 0;
	}
	private static void toggleAirplaneMode(Context context) {
		// We need to toggle the mode and also broadcast the fact.
		ContentResolver cr = context.getContentResolver();
		boolean on = Settings.System.getInt(cr,
				Settings.System.AIRPLANE_MODE_ON, 0) != 0;
		Settings.System
				.putInt(cr, Settings.System.AIRPLANE_MODE_ON, on ? 0 : 1);

		// Post the intent.
		Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
		intent.putExtra("state", !on);
		context.sendBroadcast(intent);
	}

	@Override
	public IBinder onBind(Intent arg0) {
		// TODO Auto-generated method stub
		return binder;
	}

	/**
	 * @see Binder
	 */
	public class LocalBinder extends Binder {
		public LocationService getService() {
			return LocationService.this;
		}
	}

	private ServiceConnection bluetoothDiscovererServiceConnection = new ServiceConnection() {

		@Override
		public void onServiceConnected(ComponentName className,
				final IBinder service) {
			bluetoothDiscovererService = ((BluetoothDiscovererService.LocalBinder) service)
					.getService();
			bluetoothDiscovererService.discover();
		}

		@Override
		public void onServiceDisconnected(ComponentName name) {
			bluetoothDiscovererService = null;
		}
	};

	private BroadcastReceiver bluetoothReceiver = new BroadcastReceiver() {

		@Override
		public void onReceive(Context context, Intent intent) {
			if (intent.getAction().equals(
					BluetoothDiscovererService.BLUETOOTH_ACTION)) {
				BluetoothMeasurement measurement = bluetoothDiscovererService
						.getLatestMeasurement();
				if (measurement != null) {
					btMeasurement = measurement;					
					bluetoothDiscovererService.stopService(new Intent());
					checkForMeasurements();
				}
				Log.d("WhereAmI.LocationService", "bluetoothReceived");

			}

		}
	};

	private ServiceConnection gsmDiscovererServiceConnection = new ServiceConnection() {

		@Override
		public void onServiceConnected(ComponentName className,
				final IBinder service) {
			gsmDiscovererService = ((GSMDiscovererService.LocalBinder) service)
					.getService();
			gsmDiscovererService.discover();
		}

		@Override
		public void onServiceDisconnected(ComponentName name) {
			gsmDiscovererService = null;
		}
	};

	private BroadcastReceiver gsmReceiver = new BroadcastReceiver() {

		@Override
		public void onReceive(Context context, Intent intent) {
			if (intent.getAction().equals(GSMDiscovererService.GSM_ACTION)) {
				GSMMeasurement measurement = gsmDiscovererService
						.getLatestMeasurement();
				if (measurement != null) {
					gsmMeasurement = measurement;
					gsmDiscovererService.stopService(new Intent());
					checkForMeasurements();
				}				
				Log.d("WhereAmI.LocationService", "gsmReceived");

			}

		}
	};

	private ServiceConnection wifiDiscovererServiceConnection = new ServiceConnection() {

		@Override
		public void onServiceConnected(ComponentName className,
				final IBinder service) {
			wifiDiscovererService = ((WifiDiscovererService.LocalBinder) service)
					.getService();
			wifiDiscovererService.discover();
			wifiDiscovererService.stopService(new Intent());
		}

		@Override
		public void onServiceDisconnected(ComponentName name) {
			wifiDiscovererService = null;
		}
	};

	private BroadcastReceiver wifiReceiver = new BroadcastReceiver() {

		@Override
		public void onReceive(Context context, Intent intent) {
			if (intent.getAction().equals(WifiDiscovererService.WIFI_ACTION)) {
				WiFiMeasurement measurement = wifiDiscovererService
						.getLatestMeasurement();
				if (measurement != null) {
					wifiMeasurement = measurement;
					checkForMeasurements();
					wifiDiscovererService.stopService(new Intent());
				}
				Log.d("WhereAmI.LocationService", "wifiReceived");

			}

		}
	};
	
	
	private ServiceConnection gpsDiscovererServiceConnection = new ServiceConnection() {

		@Override
		public void onServiceConnected(ComponentName className,
				final IBinder service) {
			gpsDiscovererService = ((GPSDiscovererService.LocalBinder) service)
					.getService();
			gpsDiscovererService.startTimedRepetition();
			gpsDiscovererService.stopService(new Intent());
		}

		@Override
		public void onServiceDisconnected(ComponentName name) {
			gpsDiscovererService = null;
		}
	};
	private BroadcastReceiver gpsReceiver = new BroadcastReceiver() {

		@Override
		public void onReceive(Context context, Intent intent) {
			if (intent.getAction().equals(GPSDiscovererService.GPS_ACTION)) {
				Location location = gpsDiscovererService.getLatestLocation();
				if (location != null) {
					gpsMeasurement=location;
					checkForMeasurements();
					gpsDiscovererService.stopTimedRepetition();
					gpsDiscovererService.stopService(new Intent());
				}
				Log.d("WhereAmI.LocationService", "gpsReceived");

			}

		}
	};
}